package srdb.migration.schema.metadata;

import srdb.migration.MigrationToolkit;
import srdb.migration.Utility;
import srdb.migration.common.MTKConstants;

public class Column extends DBObject {
    private String columnName = null;
    private String dataTypeStr = null;

    private String baseDataTypeStr = null;
    private String exDataType = null;
    private int dataLength = 0;
    private int dataPrecision = 0;
    private int dataScale = 0;
    private boolean nullable = false;
    private DataType dataType = null;

    private boolean caseSensitive = false;

    private String defaultClause = null;

    private String comments = null;
    private Table parentTable = null;

    private int inhCount = 0;

    public Column() {
    }

    public Column(String ColumnName) {
        this.columnName = ColumnName;
    }

    public Column(Table parentTable, String ColumnName) {
        this.parentTable = parentTable;
        this.columnName = ColumnName;
    }

    public void addDetail(String DataTypeStr, int DataLength,
                          int DataPrecision, int DataScale, String Nullable,
                          boolean caseSensitive, String defaultClause, String comments,
                          String exDataType) {
        this.dataTypeStr = (this.baseDataTypeStr = DataTypeStr);

        this.exDataType = exDataType;

        this.dataLength = DataLength;
        this.dataPrecision = DataPrecision;
        this.dataScale = DataScale;
        this.caseSensitive = caseSensitive;

        if (defaultClause != null) {
            if ((MigrationToolkit.getInstance().getSourceDBType() == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)
                    && (MigrationToolkit.getInstance().getTargetDBType() == MTKConstants.DATABASE_TYPE.ORACLE)) {
                String dc = Utility.convertEDBDateDCtoOraDateDC(defaultClause);
                if (dc != null)
                    this.defaultClause = dc;
                else {
                    this.defaultClause = defaultClause;
                }
            }

            if (MigrationToolkit.getInstance().getTargetDBType() != MTKConstants.DATABASE_TYPE.ORACLE) {
                if ((this.baseDataTypeStr.equalsIgnoreCase("INTEGER"))
                        && (this.parentTable != null)
                        && ((defaultClause.contains("nextval('"
                        + this.parentTable.getName() + "_"
                        + this.columnName + "_seq'")) || (defaultClause
                        .contains("nextval('"
                                + this.parentTable.getSchema()
                                + "." + this.parentTable.getName()
                                + "_" + this.columnName + "_seq'")))) {
                    this.dataTypeStr = "serial";
                } else if ((this.baseDataTypeStr.equalsIgnoreCase("BIGINT"))
                        && (this.parentTable != null)
                        && ((defaultClause.contains("nextval('"
                        + this.parentTable.getName() + "_"
                        + this.columnName + "_seq'")) || (defaultClause
                        .contains("nextval('"
                                + this.parentTable.getSchema()
                                + "." + this.parentTable.getName()
                                + "_" + this.columnName + "_seq'")))) {
                    this.dataTypeStr = "bigserial";
                } else if ((MigrationToolkit.getInstance().getSourceDBType() == MTKConstants.DATABASE_TYPE.ORACLE)
                        && (MigrationToolkit.getInstance().getTargetDBType() == MTKConstants.DATABASE_TYPE.SRDB)) {
                    String dc = Utility
                            .convertOraDateDCtoSrdbDateDC(defaultClause.trim());
                    if (dc != null)
                        this.defaultClause = dc;
                    else {
                        this.defaultClause = defaultClause;
                    }
                } else
                    this.defaultClause = defaultClause;
            }
        } else {
            this.defaultClause = defaultClause;
        }

        this.comments = comments;

        if ((Nullable.compareToIgnoreCase("Y") == 0)
                || (Nullable.compareToIgnoreCase("YES") == 0)
                || (Nullable.compareToIgnoreCase("1") == 0))
            this.nullable = true;
        else {
            this.nullable = false;
        }

        if (this.baseDataTypeStr.equalsIgnoreCase("ARRAY")) {
            this.dataType = DataType.ARRAY;
            this.dataTypeStr = exDataType;
        } else if (isInterval()) {
            this.dataType = DataType.INTERVAL;

            if (exDataType != null)
                this.dataTypeStr = exDataType;
        } else if (isBit()) {
            this.dataType = DataType.BIT;

            if (exDataType != null)
                this.dataTypeStr = exDataType;
        } else if (isBitString()) {
            this.dataType = DataType.BITSTRING;

            if (exDataType != null)
                this.dataTypeStr = exDataType;
        } else if (isVarchar()) {
            this.dataType = DataType.VARCHAR;
        } else if (isNVarchar()) {
            this.dataType = DataType.NVARCHAR;

            if (MigrationToolkit.getInstance().getTargetDBType() != MTKConstants.DATABASE_TYPE.NPS) {
                this.dataTypeStr = this.dataTypeStr.substring(1,
                        this.dataTypeStr.length());
            }
        } else if (isText()) {
            this.dataType = DataType.TEXT;

            if (this.baseDataTypeStr.toUpperCase().startsWith("NCLOB"))
                this.dataTypeStr = "CLOB";
        } else if (isDate()) {
            this.dataType = DataType.DATE;
        } else if (isNumeric()) {
            if (isFloat())
                this.dataType = DataType.FLOAT;
            else if (isBinaryFloat())
                this.dataType = DataType.BINARY_FLOAT;
            else if (isInteger())
                this.dataType = DataType.INTEGER;
            else
                this.dataType = DataType.NUMERIC;
        } else if (isTime()) {
            this.dataType = DataType.TIME;
        } else if (isTimeStamp()) {
            this.dataType = DataType.TIMESTAMP;
            if ((MigrationToolkit.getInstance().getSourceDBType() == MTKConstants.DATABASE_TYPE.SQLSERVER)
                    && (MigrationToolkit.getInstance().getTargetDBType() == MTKConstants.DATABASE_TYPE.SRDB)) {
                if (this.dataTypeStr.compareToIgnoreCase("DATETIME") == 0)
                    this.dataTypeStr = "TIMESTAMP";
            }
        } else if (isLargeObject()) {
            this.dataType = DataType.BYTEA;
        } else if (isRowID()) {
            this.dataType = DataType.ROWID;
        } else if (isBoolean()) {
            this.dataType = DataType.BOOLEAN;
        } else if (isMoney()) {
            this.dataType = DataType.MONEY;
        } else if (isXML()) {
            this.dataType = DataType.XML;
        } else if (isGeometric()) {
            this.dataType = DataType.GEOMETRIC;
        } else if (isNetworkAddress()) {
            this.dataType = DataType.NETWORKADDRESS;
        } else if (isOID()) {
            this.dataType = DataType.OID;
        } else if (isNAME()) {
            this.dataType = DataType.NAME;
        } else if (isUserDefined()) {
            this.dataType = DataType.USERDEFINED;
        } else if (isGUID()) {
            this.dataType = DataType.GUID;
        } else {
            this.dataType = DataType.OTHER;
        }
    }

    public String getName() {
        return this.columnName;
    }

    public String getDataTypeString() {
        if ((this.exDataType == null)
                || ((this.exDataType.startsWith(this.baseDataTypeStr)) && (!this.baseDataTypeStr
                .equalsIgnoreCase("RAW")))) {
            return this.dataTypeStr;
        }

        this.dataLength = (this.dataPrecision = this.dataScale = 0);
        return this.exDataType;
    }

    public DataType getDataType() {
        return this.dataType;
    }

    public int getLength() {
        return this.dataLength;
    }

    public int getPrecision() {
        return this.dataPrecision;
    }

    public int getScale() {
        return this.dataScale;
    }

    public boolean isNullable() {
        return this.nullable;
    }

    public boolean isBit() {
        if ((MigrationToolkit.getInstance().getSourceDBType() == MTKConstants.DATABASE_TYPE.SRDB)
                || (MigrationToolkit.getInstance().getSourceDBType() == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)) {
            return false;
        }

        return this.dataTypeStr.equalsIgnoreCase("BIT");
    }

    public boolean isVarchar() {
        return (this.dataTypeStr.compareToIgnoreCase("VARCHAR2") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("VARCHAR") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("CHAR") == 0)
                || (this.dataTypeStr.equalsIgnoreCase("CHARACTER"))
                || (this.dataTypeStr.equalsIgnoreCase("CHARACTER VARYING"));
    }

    public boolean isNVarchar() {
        return (this.dataTypeStr.compareToIgnoreCase("NVARCHAR2") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("NCHAR") == 0);
    }

    public boolean isText() {
        return
                //mod by kevin
				(this.dataTypeStr.compareToIgnoreCase("LONG") == 0)
				|| (this.dataTypeStr.compareToIgnoreCase("LONG VARCHAR") == 0)
				||
                
                (this.dataTypeStr.compareToIgnoreCase("CLOB") == 0)
                        || (this.dataTypeStr.compareToIgnoreCase("NCLOB") == 0)
                        || (this.dataTypeStr.equalsIgnoreCase("TEXT"))
                        || (this.dataTypeStr.compareToIgnoreCase("VARGRAPHIC") == 0);
    }

    public boolean isNumeric() {
        return (this.dataTypeStr.equalsIgnoreCase("NUMBER"))
                || (this.dataTypeStr.equalsIgnoreCase("NUMERIC"))
                || (this.dataTypeStr.toUpperCase().startsWith("FLOAT"))
                || (this.dataTypeStr.equalsIgnoreCase("DOUBLE"))
                || (this.dataTypeStr.equalsIgnoreCase("DECIMAL"))
                || (this.dataTypeStr.equalsIgnoreCase("INTEGER"))
                || (this.dataTypeStr.equalsIgnoreCase("INT"))
                || (this.dataTypeStr.equalsIgnoreCase("SMALLINT"))
                || (this.dataTypeStr.equalsIgnoreCase("BIT"))
                || (this.dataTypeStr.equalsIgnoreCase("TINYINT"))
                || (this.dataTypeStr.equalsIgnoreCase("MEDIUMINT"))
                || (this.dataTypeStr.equalsIgnoreCase("BIGINT"))
                || (this.dataTypeStr.equalsIgnoreCase("REAL"))
                || (this.dataTypeStr.equalsIgnoreCase("DOUBLE PRECISION"))
                || (this.dataTypeStr.equalsIgnoreCase("YEAR"))
                || (this.dataTypeStr.equalsIgnoreCase("SERIAL"))
                || (this.dataTypeStr.equalsIgnoreCase("BIGSERIAL"))
                || (this.dataTypeStr.equalsIgnoreCase("BINARY_DOUBLE"))
                || (this.dataTypeStr.equalsIgnoreCase("BINARY_FLOAT"));
    }

    public boolean isFloat() {
        return (this.dataTypeStr.toUpperCase().startsWith("FLOAT"))
                || (this.dataTypeStr.equalsIgnoreCase("DOUBLE PRECISION"))
                || (this.dataTypeStr.equalsIgnoreCase("REAL"))
                || (this.dataTypeStr.equalsIgnoreCase("DOUBLE"))
                || (this.dataTypeStr.equalsIgnoreCase("DECIMAL"))
                || (this.dataTypeStr.equalsIgnoreCase("BINARY_DOUBLE"));
    }

    public boolean isBinaryFloat() {
        return this.dataTypeStr.equalsIgnoreCase("BINARY_FLOAT");
    }

    public boolean isInteger() {
        return (isNumeric()) && ((this.dataScale == 0) || (isSmallint()));
    }

    public boolean isDate() {
        return this.dataTypeStr.compareToIgnoreCase("DATE") == 0;
    }

    public boolean isTime() {
        return (this.dataTypeStr.compareToIgnoreCase("TIME") == 0)
                || (this.dataTypeStr.equalsIgnoreCase("TIME WITHOUT TIME ZONE"))
                || (this.dataTypeStr.equalsIgnoreCase("TIME WITH TIME ZONE"));
    }

    public boolean isTimeStamp() {
        if ((this.dataTypeStr.equalsIgnoreCase("DATETIME"))
                || (this.dataTypeStr.equalsIgnoreCase("DATETIME2"))
                || (this.dataTypeStr.equalsIgnoreCase("DATETIMEOFFSET"))) {
            return true;
        }

        if ((this.dataTypeStr != null)
                && (this.dataTypeStr.trim().length() >= 9)) {
            String typeName = this.dataTypeStr.trim().substring(0, 9);

            if (typeName.compareToIgnoreCase("TIMESTAMP") == 0) {
                return true;
            }
        }

        return false;
    }

    public boolean isLargeObject() {
        return (this.dataTypeStr.compareToIgnoreCase("LONG RAW") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("BLOB") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("RAW") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("BYTEA") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("BINARY") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("VARBINARY") == 0)
                //add by kevin
//                || (this.dataTypeStr.compareToIgnoreCase("LONG") == 0)
//                || (this.dataTypeStr.compareToIgnoreCase("LONG VARCHAR") == 0)
                ;
    }

    public boolean isRowID() {
        return (this.dataTypeStr.equalsIgnoreCase("ROWID"))
                || (this.dataTypeStr.equalsIgnoreCase("UROWID"));
    }

    public boolean isLong() {
        return (this.dataTypeStr.compareToIgnoreCase("LONG") == 0)
                || (this.dataTypeStr.compareToIgnoreCase("LONG VARCHAR") == 0);
    }

    public boolean isInterval() {
        return (this.dataTypeStr.equalsIgnoreCase("INTERVAL"))
                || (this.dataTypeStr.toUpperCase().startsWith("INTERVAL"));
    }

    public boolean isDecimal() {
        return this.dataTypeStr.compareToIgnoreCase("DECIMAL") == 0;
    }

    public boolean isDouble() {
        return (this.dataTypeStr.toUpperCase().startsWith("DOUBLE"))
                || (this.dataTypeStr.equalsIgnoreCase("BINARY_DOUBLE"));
    }

    public boolean isReal() {
        return this.dataTypeStr.toUpperCase().startsWith("REAL");
    }

    public boolean isCaseSensitive() {
        return this.caseSensitive;
    }

    public boolean isSmallint() {
        return (this.dataTypeStr.equalsIgnoreCase("SMALLINT"))
                || (this.dataTypeStr.equalsIgnoreCase("TINYINT"));
    }

    public boolean isBlob() {
        return this.dataTypeStr.equalsIgnoreCase("BLOB");
    }

    public boolean isLongRaw() {
        return this.dataTypeStr.equalsIgnoreCase("LONG RAW");
    }

    public boolean isClob() {
        return this.dataTypeStr.equalsIgnoreCase("CLOB");
    }

    public boolean isNClob() {
        return this.dataTypeStr.equalsIgnoreCase("NCLOB");
    }

    public int getBufferStorageSize() {
        if (isNumeric())
            return 38;
        if ((isDate()) || (isTime()) || (isTimeStamp())) {
            return 30;
        }

        if ((this.dataTypeStr.equalsIgnoreCase("TEXT"))
                || (this.dataTypeStr.equalsIgnoreCase("XML"))) {
            return 1024;
        }

        return this.dataLength;
    }

    public String getDefaultClause() {
        return this.defaultClause;
    }

    public String getComments() {
        return this.comments;
    }

    public String getTableName() {
        return this.parentTable != null ? this.parentTable.getName() : null;
    }

    public void setCaseSensitive(boolean value) {
        this.caseSensitive = value;
    }

    public boolean isBigInt() {
        return this.dataTypeStr.equalsIgnoreCase("BIGINT");
    }

    public DBObject getParent() {
        return this.parentTable;
    }

    public String getSchema() {
        if (this.parentTable != null) {
            return this.parentTable.getSchema();
        }
        return null;
    }

    public boolean isWholeNumberType() {
        return (this.dataTypeStr.equalsIgnoreCase("INTEGER"))
                || (this.dataTypeStr.equalsIgnoreCase("BIGINT"))
                || (this.dataTypeStr.equalsIgnoreCase("SERIAL"))
                || (this.dataTypeStr.equalsIgnoreCase("BIGSERIAL"))
                || (isSmallint());
    }

    public boolean isBoolean() {
        return this.dataTypeStr.equalsIgnoreCase("BOOLEAN");
    }

    public boolean isMoney() {
        return (this.dataTypeStr.equalsIgnoreCase("MONEY"))
                || (this.dataTypeStr.equalsIgnoreCase("SMALLMONEY"));
    }

    public boolean isXML() {
        return (this.dataTypeStr.equalsIgnoreCase("XML"))
                || (this.dataTypeStr.equalsIgnoreCase("XMLTYPE"));
    }

    public boolean isGeometric() {
        return (this.dataTypeStr.equalsIgnoreCase("POINT"))
                || (this.dataTypeStr.equalsIgnoreCase("LINE"))
                || (this.dataTypeStr.equalsIgnoreCase("LSEG"))
                || (this.dataTypeStr.equalsIgnoreCase("BOX"))
                || (this.dataTypeStr.equalsIgnoreCase("PATH"))
                || (this.dataTypeStr.equalsIgnoreCase("POLYGON"))
                || (this.dataTypeStr.equalsIgnoreCase("CIRCLE"));
    }

    public boolean isBitString() {
        return (this.dataTypeStr.equalsIgnoreCase("BIT VARYING"))
                || (this.dataTypeStr.equalsIgnoreCase("BIT"));
    }

    public boolean isNetworkAddress() {
        return (this.dataTypeStr.equalsIgnoreCase("CIDR"))
                || (this.dataTypeStr.equalsIgnoreCase("INET"))
                || (this.dataTypeStr.equalsIgnoreCase("MACADDR"));
    }

    public boolean isOID() {
        return this.dataTypeStr.equalsIgnoreCase("OID");
    }

    public boolean isNAME() {
        return this.dataTypeStr.equalsIgnoreCase("NAME");
    }

    public boolean isUserDefined() {
        return this.dataTypeStr.equalsIgnoreCase("USER-DEFINED");
    }

    public boolean isGUID() {
        return (this.dataTypeStr.equalsIgnoreCase("UUID"))
                || (this.dataTypeStr.equalsIgnoreCase("UNIQUEIDENTIFIER"));
    }

    public int getInhCount() {
        return this.inhCount;
    }

    public void setInhCount(int inhCount) {
        this.inhCount = inhCount;
    }

    public static enum DataType {
        // VARCHAR, NVARCHAR, INTEGER, NUMERIC, FLOAT, DATE, TIME, TIMESTAMP,
        // TEXT, BYTEA, ROWID, INTERVAL, BIT, BOOLEAN, MONEY, XML, ARRAY,
        // GEOMETRIC, BITSTRING, NETWORKADDRESS, OID, NAME, USERDEFINED, GUID,
        // BINARY_FLOAT, OTHER;
        VARCHAR, NVARCHAR, INTEGER, NUMERIC, FLOAT, DATE, TIME, TIMESTAMP, TEXT, BYTEA, ROWID, INTERVAL, BIT, BOOLEAN, MONEY, XML, ARRAY, GEOMETRIC, BITSTRING, NETWORKADDRESS, OID, NAME, USERDEFINED, GUID, BINARY_FLOAT, OTHER;
    }
}

/*

 */